#include "window.h"

Window::Window(LPCTSTR appClassName, LPCTSTR wndCaption)
{
	_appClassName				= appClassName;
	_wndCaption					= wndCaption;
	_hAppInstance				= GetModuleHandle(NULL);

    _wndClass.style 			= CS_HREDRAW | CS_VREDRAW;
    _wndClass.lpfnWndProc		= this->StaticWindowProcedure;			// Window Procedure: mandatory
    _wndClass.cbClsExtra		= 0;
    _wndClass.cbWndExtra		= 0;
    _wndClass.hInstance			= _hAppInstance;						// owner of the class: mandatory
    _wndClass.hIcon				=
    	(HICON)::LoadImage(NULL, TEXT(".\\res\\icon.ico"), IMAGE_ICON, 64, 64, LR_LOADFROMFILE);
    _wndClass.hCursor			= ::LoadCursor(0, IDC_ARROW);			// optional
    _wndClass.hbrBackground		= (HBRUSH) (COLOR_WINDOW + 1);			// optional
    _wndClass.lpszMenuName		= 0;
    _wndClass.lpszClassName		= _appClassName;						// mandatory
}

Window::~Window()
{
	if( _wModel )
		delete _wModel;	// 2
	if( _wView )
		delete _wView;	// 1
}

void Window::ShowWindow()
{
	HWND hWnd;

	// Register the window under the name "_appClassName"
	this->Register();
	// Create the window in memory
	hWnd	= this->Create();
	_wView	= new WindowView(hWnd);				// 1
	_wModel	= new WindowModel(hWnd, _wView);	// 2
	// This will show you the window
	this->Show(SW_SHOW);
	// The window goes message loop
	this->MessageLoop();
}

void Window::Register()
{
    ::RegisterClass(&_wndClass);
}

HWND Window::Create()
{
	return _hWnd = ::CreateWindow(
		_appClassName,  		// name of a registered window class
        _wndCaption,            // window caption
        WS_OVERLAPPEDWINDOW,    // window style
        CW_USEDEFAULT,          // x position
        CW_USEDEFAULT,          // y position
        640,         			// witdh
        480,          			// height
        0,                      // handle to parent window
        0,                      // handle to menu
        _hAppInstance,   	    // application instance
        (void *)this);          // window creation data
}

void Window::Show(int cmdShow)
{
	::ShowWindow(_hWnd, cmdShow);
	::UpdateWindow(_hWnd);
}

void Window::MessageLoop()
{
	MSG msg;
    int status;

	// Run the message loop. It will run until GetMessage() returns 0
    while( (status = ::GetMessage (&msg, _hWnd, 0, 0)) != 0 )
    {
        // Translate virtual-key messages into character messages
        ::TranslateMessage(&msg);
        // Send message to WindowProcedure
        ::DispatchMessage(&msg);
    }
}

LRESULT CALLBACK Window::StaticWindowProcedure
	(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	Window *w;

	if( message == WM_NCCREATE )
		SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT(lParam))->lpCreateParams));

	w = (Window *)GetWindowLongPtr(hWnd, GWLP_USERDATA);

	if( w )
		return w->WindowProcedure(hWnd, message, wParam, lParam);
	else
	// All the unprocessed messages go there, to be dealt in some default way
		return DefWindowProc(hWnd, message, wParam, lParam);
}

HWND Window::getHWND()
{
	return _hWnd;
}
